import Router from 'koa-router'
import config from './config'
import path from 'path'
import { prefixSymbol } from './controller'
import fs from 'fs'

import requireDirectory from 'require-directory'

let routeMap = {get:[],post:[],put:[],delete:[],all:[]};
const apis = requireDirectory(module, path.resolve(__dirname, '../api'));
const controllers = requireDirectory(module, path.resolve(__dirname,'../controller'));

export function get(url) {
    return (target, name, description) => {
        routeMap.get.push({
            url: url,
            target: target,
            method: name,
            params:(description.value.toString().match(/function\s+\w+\(([\s\S]*)\)\s*\{/))[1]
                .split(',').map(item => item.trim())
        })
        return description
    }
}
export function post(url) {
    return (target, name, description) => {
        routeMap.post.push({
            url: url,
            target: target,
            method: name,
            params:(description.value.toString().match(/function\s+\w+\(([\s\S]*)\)\s*\{/))[1]
                .split(',').map(item => item.trim())
        })
        return description
    }
}
export function put(url) {
    return (target, name, description) => {
        routeMap.put.push({
            url: url,
            target: target,
            method: name,
            params:(description.value.toString().match(/function\s+\w+\(([\s\S]*)\)\s*\{/))[1]
                .split(',').map(item => item.trim())
        })
        return description
    }
}
export function del(url) {
    return (target, name, description) => {
        routeMap.delete.push({
            url: url,
            target: target,
            method: name,
            params:(description.value.toString().match(/function\s+\w+\(([\s\S]*)\)\s*\{/))[1]
                .split(',').map(item => item.trim())
        });
        return description;
    };
}
export function all(url) {
    return (target, name, description) => {
        routeMap.all.push({
            url: url,
            target: target,
            method: name,
            params:(description.value.toString().match(/function\s+\w+\(([\s\S]*)\)\s*\{/))[1]
                .split(',').map(item => item.trim())
        });
        return description;
    }
}

function minix_controller(target) {
    let temp = () => {
        return {
            code: 2000,
            msg: '',
            data: {},
            url:'',
            setContext(ctx, next) {
                this.ctx = ctx;
                this.session = this.ctx.session;
                this.next = next;
                console.log('body===>', ctx.request.body);
                this.params = ctx.method === 'POST' ? ctx.request.body : ctx.query
            },
            setCode(code) {
                this.code = code
                return this
            },
            setMsg(msg) {
                this.msg = msg
                return this
            },
            setUrl(url) {
              this.url = url
              return this
            },
            assign(key, val) {
                this.data[key] = val
                return this
            },
            json() {
                this.ctx.type = 'json'
                return JSON.stringify({code: this.code, msg: this.msg, data: this.data,url:this.url})
            },
            redirect(url) {
                this.ctx.redirect(url)
            },
            raw(data) {
                return data
            },
            fetch(file) {
                let real_path = path.resolve(__dirname,`../${config.views.root}/${file}.${config.views.extname}`);
                return new Promise((resolve, reject) => {
                    fs.stat(real_path, (err, stats) => {
                        if(err) {
                            reject(err)
                        }else {
                            if(!stats.isFile()) {
                                reject('文件不存在')
                            }else{
                                fs.readFile(real_path, (err, data) => {
                                    if(err) {
                                        reject(err)
                                    }else {
                                        resolve(data.toString())
                                    }
                                })
                            }
                        }
                    });
                })
            },
            async __todo(fn, ...args) {
                let callback = fn.bind(this)
                return await callback(...args)
            }
        }
    }
    return Object.assign(target, temp())
}

export function route(app, options){
    let router = Router(app),
        root = '/',
        redirect = options && (options.redirect || {})
    for(let method in routeMap) {
        for(let _ of routeMap[method]) {
            let target_url =  _.url.startsWith('/')?_.url:`/${_.url}`
            router[method](_.target[prefixSymbol]?(_.target[prefixSymbol]  + target_url):target_url, async (ctx, next) => {
                let context = Object.create(_.target)
                context = minix_controller(context)
                context.setContext(ctx, next)
                try{
                    let params = _.params.map(item => ctx.params[item])
                    let res = await context[_.method](params)
                    if(res !== undefined)
                        ctx.body = res
                }catch(err) {
                    ctx.body = err
                }
            })
        }
    }
    return router.routes()
}

